package sip.oshima.ua.websocket;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import sip.oshima.ua.SipClient;
import sip.oshima.ua.domain.SipUserInfo;
import sip.oshima.ua.util.SpringContextUtil;

import javax.annotation.PreDestroy;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
@ServerEndpoint("/sip")
public class WebSocketServer {

    private static final List<Session> USERS = new ArrayList<>();
    private static Session USER;

    public static void sendMsg(Session session, String message) {
        if (session != null) {
            try {
                log.debug(message);
                if (session.isOpen()) {
                    session.getBasicRemote().sendText(message);
                } else {
                    log.debug("链接已关闭，取消发送");
                }
            } catch (Exception e) {
                log.error("发送消息异常:{}", e.getMessage());
            }
        } else {
            log.info("你已离线");
        }
    }

    public static void sendMsg(Session session, String... params) {
        JSONObject json = new JSONObject();
        // 默认code 为消息
        json.set("code", "msg");
        for (int i = 0; i < params.length; i += 2) {
            json.set(params[i], params[i + 1]);
        }
        sendMsg(session, json.toString());
    }

    /**
     * 将消息发送给最新的用户
     *
     * @param params 信息
     */
    public static void sendMsg(String... params) {
        sendMsg(USER, params);
    }

    /**
     * 链接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) throws Exception {
        clearOldConnect();
        USERS.add(session);
        USER = session;
        log.debug("当前链接用户数：onOpen\t：{}", USERS.size());
        SipClient.getInstance().destroy();
        sendMsg("code", "open", "msg", "链接成功",
                "version", SpringContextUtil.getProperty("sip.version"));
    }


    /**
     * 链接关闭时处理
     */
    @OnClose
    public void onClose(Session session) {
        log.info("关闭链接 - {}", session);
        log.debug("当前链接用户数：session\t：{}", USERS.size());
        if (USERS.size() <= 1) {
            USERS.clear();
            USER = null;
            log.warn("当前链接全部离线");
        }
    }

    /**
     * 服务器接收到客户端消息时调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        JSONObject msg = JSONUtil.parseObj(message);
        String code = msg.getStr("code");
        switch (code) {
            // 创建用户代理
            case "createUserAgent":
                SipUserInfo sipUserInfo = msg.getBean("data", SipUserInfo.class);
                if (StrUtil.hasBlank(sipUserInfo.getNumber(), sipUserInfo.getPwd(), sipUserInfo.getServer())) {
                    sendMsg(session, "msg", "配置参数不完整");
                    break;
                }
                SipClient.getInstance().createUserAgent(sipUserInfo);
                break;
            // 销毁用户代理
            case "destroyUserAgent":
                SipClient.getInstance().destroy();
                break;
            // 接通电话
            case "pickup":
                SipClient.getInstance().pickup();
                break;
            // 挂电话
            case "hangup":
                SipClient.getInstance().hangup();
                break;
            // 打电话
            case "call":
                SipClient.getInstance().call(msg.getStr("data"));
                break;

        }

    }

    private void clearOldConnect() {
        while (USERS.iterator().hasNext()) {
            Session user = USERS.iterator().next();
            sendMsg(user, "code", "close", "msg", "有新的链接加入，当前链接关闭");
            try {
                user.close();
            } catch (IOException e) {
                log.error("关闭链接失败，{}", e.getMessage());
            }
        }
        USERS.clear();
    }

    @PreDestroy
    public void destroy() {
        SipClient.getInstance().destroy();
    }


}
